<html>
<head>
<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="Cache-Control" content="no-cache"/>
<meta http-equiv="Expires" content="-1" />
<title>Web Services - Sample 05: Using XMLHttpRequest from JavaScript</title>

<style><!--
a{text-decoration:none;
  padding: 1px;
  background-color: #dddddd}
--></style>

<script type="text/javascript">

function newRequest() { // return a new request object
    request = null;
    if (window.XMLHttpRequest)
        request = new XMLHttpRequest();
    else if (window.ActiveXObject)
        request = new ActiveXObject('Microsoft.XMLHTTP');
    if (request == null) alert('No XMLHttpRequest support');
    return request;
}

function cmd(suffix) { // apply synchronously and return JSON result
    req = newRequest();
    req.open('get',
             '/apply/pymol.cmd.' + suffix + 
             ( suffix.indexOf('?') < 0 ? '?' : '&') +
             "_ts=" + new Date().getTime(),
             false); // synchronous
    req.setRequestHeader("Accept", "application/json");
    req.send("");
    if (req.status == 500) {
       alert("PyMOL Exception:\n" + eval('(' + req.responseText + ')').join("\n"));
       return null;
    } 
    return eval('(' + req.responseText + ')');
}

function alignAll() { // Javascript loop which performs the alignment

    var obj_list = cmd("get_names"); // get current objects

    for(i=1;i<obj_list.length;i++) { // align all to first object

        result = cmd("align?mobile=" + obj_list[i] + "////CA" + 
                     "&target=" + obj_list[0] + "////CA");
    }

    if(obj_list.length) {
        cmd("center?selection=" + obj_list[0]); // recenter on first object 
    }
}

function refreshTable()
{
    var obj_list = cmd("get_names");
    var enabled = cmd("get_names?enabled_only=1");
    var table = document.getElementById("obj_table");
    var body = table.tBodies[0];
    var nTableRows = body.rows.length;
    var nListRows = obj_list.length;
    var i = 0;
    updateRow = function(row,name,enabled) {
        method = 'enable';    
        for(j=0;j<enabled.length;j++) {
            if (enabled[j]==name) {
               method = 'disable';
               break;
             } 
        }
        row.cells[0].innerHTML = name;
        row.cells[1].innerHTML = "<a href=\"javascript:void(0)\" onclick=\"cmd('" +
            method+"?name="+name+"');refreshTable();\">"+method+"</a>";
        row.cells[2].innerHTML = "<a href=\"javascript:void(0)\" onclick=\"cmd('" +
            "show_as?representation=sticks&selection=organic and "+name+"')\">ligand as sticks</a>";     
        row.cells[3].innerHTML = "<a href=\"javascript:void(0)\" onclick=\"cmd('" +
            "orient?selection=organic and "+name+"&animate=2')\">orient ligand</a>";     
        row.cells[4].innerHTML = "<a href=\"javascript:void(0)\" onclick=\"cmd('" +
            "show?representation=lines&selection=byres "+name+" within 5 of (organic and "+name+")')\">show binding site</a>";     
        row.cells[5].innerHTML = "<a href=\"javascript:void(0)\" onclick=\"cmd('" +
            "delete?name="+name+"'); refreshTable();\">delete</a>";     
    }
    while ((i<nTableRows) && (i<nListRows)) {
        updateRow(body.rows[i], obj_list[i], enabled);
        i++;
    }
    while (i<nListRows) {
        body.insertRow(-1);
        var row = body.rows[i];
        row.insertCell(0);
        row.insertCell(0);
        row.insertCell(0);
        row.insertCell(0);
        row.insertCell(0);
        row.insertCell(0);
        updateRow(row, obj_list[i], enabled);
        i++;
    }
    while (i<nTableRows) {
        body.deleteRow(nTableRows-1);
        nTableRows--;
    }
    return false;
}

function loadPDB(code)
{
   return cmd('load?filename=$PYMOL_PATH/modules/web/examples/data/'+code+'.pdb');
}

</script>
</head>
<body onload="refreshTable()">
<h3>Web Services - Sample 05: Using XMLHttpRequest from JavaScript</h3>

<p> Now we complicate the situation by relying upon the XMLHttpRequest
method which sits at the heart of AJAX.  

TODO: change tone to explain why this is beneficial

However, in this example, we
stick with simple synchronous requests which can return results and
state information from PyMOL.</p>

<a href="/apply/_quit">quit pymol</a>

(FireFox only: <a href="javascript:void(0)" onclick="window.open('view-source:' + location.href)">view page source</a>)

<p><b>Structures</b></p>

<pre>
<a href="javascript:void(0)" 
 onclick="loadPDB('1iqj'); refreshTable();">loadPDB('1iqj'); refreshTable();</a>

<a href="javascript:void(0)" 
 onclick="loadPDB('2fzz'); refreshTable();">loadPDB('2fzz'); refreshTable();</a>

<a href="javascript:void(0)" 
 onclick="loadPDB('2g00'); refreshTable();">loadPDB('2g00'); refreshTable();</a>

<a href="javascript:void(0)" 
 onclick="loadPDB('missing'); refreshTable();">loadPDB('missing'); refreshTable();</a> (will display Python exception / traceback)

<a href="javascript:void(0)" onclick="cmd('delete?name=all'); refreshTable();">cmd('delete?name=all'); refreshTable();</a> 
</pre>

<p>Likewise, the table below is updated from JavaScript, based on what objects are currently loaded inside PyMOL.</p>

<p>TODO make these buttons behave better</p>

<table id="obj_table" border=1><tbody></tbody></table>

<pre><a href="javascript:void(0)" onclick="refreshTable()">refreshTable()</a></pre>

<p>The alignAll command source below illustrates how you can program
PyMOL from JavaScript using synchronous requests which return JSON object
results from PyMOL that are then subsequently acted upon.</p>

<pre>
function alignAll() { // Javascript loop which performs the alignment

    var obj_list = cmd("get_names"); // get current objects

    for(i=1;i&lt;obj_list.length;i++) { // align all to first object

        result = cmd("align?mobile=" + obj_list[i] + "////CA" + 
                     "&target=" + obj_list[0] + "////CA");
    }

    if(obj_list.length) {
        cmd("center?selection=" + obj_list[0]); // recenter on first object 
    }
}
</pre>

<p><b>Actions</b></p>

<pre>
<a href="javascript:void(0)" onclick="cmd('zoom?animate=2')">cmd('zoom?animate=2')</a> 

<a href="javascript:void(0)" onclick="cmd('show_as?representation=ribbon')">cmd('show_as?representation=ribbon')</a> 

<a href="javascript:void(0)" onclick="alignAll()">alignAll()</a> 
</pre>

</body>
</html>
